package com.onlocation.gui;

import android.app.ActivityManager;
import android.app.ListActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import com.onlocation.db.DatabaseHelper;
import com.onlocation.objects.LocalArrayAdapter;
import com.onlocation.objects.OkCancelDialog;
import com.onlocation.R;
import com.onlocation.services.LocatorService;
import com.onlocation.util.*;

import java.util.ArrayList;
import java.util.List;

/**
 * Author: Steve Carrell
 * Date: 5/9/12
 */
public class Main extends ListActivity {
    public static final String CLASS_NAME = Main.class.getName();
    public static final String BROADCAST_ACTION = Main.class.getName() + "_BROADCAST";

    private final DatabaseHelper db = DatabaseHelper.getInstance(this);

    private ArrayList<String> locations = new ArrayList<String>();
    private LocalArrayAdapter adapter = null;
    private boolean isStarted = false;

    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int flag = intent.getExtras().getInt("flag", 0);
            Logger.d(String.format("received flag: %d", flag), CLASS_NAME);

            switch (flag) {
                case LocatorService.FLAG_ABORT:
                    doStop(false);
                    setStartStopBtnText();
                    break;
                case LocatorService.FLAG_UPDATE:
                    adapter.updateCurrentLocation(LocatorService.getCurrentLocation());
                    break;
                default:
                    break;
            }
        }
    };

    private OnItemLongClickListener listItemLongClickListener = new OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            // if long click is on default or add location, immediately go to editLocation. Do not show context menu.
            if (StringUtil.equalsIgnoreNull((String) getListAdapter().getItem(position),
                    ResourceUtil.getString(R.string.defaultLocation)) ||
                    StringUtil.equalsIgnoreNull((String) getListAdapter().getItem(position),
                            ResourceUtil.getString(R.string.addLocation))) {
                startEditLocation(position);
                return true;
            }
            return false;
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        Util.init(this);
        populateLocations();
        getListView().setOnItemLongClickListener(listItemLongClickListener);
        registerForContextMenu(getListView());
        if (isServiceRunning()) {
            doStart(false);
        }
        setStartStopBtnText();
        adapter.updateCurrentLocation(LocatorService.getCurrentLocation());
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (adapter != null) {
            adapter.updateCurrentLocation(LocatorService.getCurrentLocation());
        }
    }

    public void onClick_startStopBtn(View view) {
        Logger.v("start/stop button clicked", CLASS_NAME);
        Button startStopBtn = (Button) view;
        if (!isStarted) {
            startStopBtn.setEnabled(false);
            doStart(true);
            setStartStopBtnText();
            startStopBtn.setEnabled(true);
        } else {
            startStopBtn.setEnabled(false);
            doStop(true);
            setStartStopBtnText();
            startStopBtn.setEnabled(true);
        }
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        startEditLocation(position);
    }

    private void startEditLocation(int position) {
        Logger.v("opening EditLocation activity", CLASS_NAME);
        boolean isNewLocation = position < 0 ||
                StringUtil.equalsIgnoreNull(adapter.getItem(position),
                        ResourceUtil.getString(R.string.addLocation));
        boolean allowNameEdit = isNewLocation ||
                !StringUtil.equalsIgnoreNull(adapter.getItem(position),
                        ResourceUtil.getString(R.string.defaultLocation));

        Bundle send = new Bundle();
        send.putBoolean("allowNameEdit", allowNameEdit);
        send.putBoolean("isNewLocation", isNewLocation);
        send.putStringArrayList("locations", locations);
        send.putInt("position", position);

        Intent intent = new Intent(this, EditLocation.class);
        intent.putExtras(send);

        startActivityForResult(intent, EditLocation.EDIT_LOCATION_REQUEST_CD);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == EditLocation.EDIT_LOCATION_REQUEST_CD &&
                resultCode == EditLocation.EDIT_LOCATION_RESULT_CD &&
                data.getExtras().getBoolean("refreshLocations")) {
            Logger.d("rebuilding location list", CLASS_NAME);
            populateLocations();
        }
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.main_context_menu, menu);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.options_menu, menu);
        return true;
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        switch(item.getItemId()) {
            case R.id.edit:
                startEditLocation(info.position);
                break;
            case R.id.delete:
                final String location = (String) getListAdapter().getItem(info.position);
                OkCancelDialog dlg = new OkCancelDialog(this, "",
                        String.format(ResourceUtil.getString(R.string.deleteConfirm), location)) {
                    protected void okAction() {
                        db.deleteLocation(location);
                        populateLocations();
                        Toast.makeText(getBaseContext(),
                                String.format(ResourceUtil.getString(R.string.delete), location),
                                Toast.LENGTH_SHORT);
                    }
                };
                dlg.show();
                break;
            default:
                break;
        }
        return super.onContextItemSelected(item);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menuitem_settings:
                startActivity(new Intent(this, Preferences.class));
                break;
            case R.id.menuitem_newLocation:
                startEditLocation(-1);
                break;
        }
        return true;
    }

    @Override
    protected void onDestroy() {
        if (isStarted && isFinishing()) {
            Logger.d("exiting application", CLASS_NAME);
            unregisterReceiver(receiver);
        }
        super.onDestroy();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    private void populateLocations() {
        locations.clear();
        locations.addAll(db.getLocationList());
        locations.remove(ResourceUtil.getString(R.string.defaultLocation));
        locations.add(0, ResourceUtil.getString(R.string.defaultLocation));
        locations.add(ResourceUtil.getString(R.string.addLocation));

        if (adapter == null) {
            adapter = new LocalArrayAdapter(this, locations);
            setListAdapter(adapter);
        } else {
            adapter.notifyDataSetChanged();
        }

        if (isStarted) {
            // Let the service know we need to rebuild our location map.
            sendBroadcast(LocatorService.FLAG_NEW_DATA);
        }
    }

    private void setStartStopBtnText() {
        Button startStopBtn = (Button) findViewById(R.id.startStopBtn);
        if (isStarted) {
            startStopBtn.setText(R.string.stop);
        } else {
            startStopBtn.setText(R.string.start);
        }
    }

    private void doStart(boolean doStartService) {
        Logger.d("starting LocatorService", CLASS_NAME);
        isStarted = true;
        IntentFilter intentFilter = new IntentFilter(LocatorService.BROADCAST_ACTION);
        registerReceiver(receiver, intentFilter);
        // If we're calling doStart from onCreate, the service is already running.
        if (doStartService) {
            startService(new Intent(this, LocatorService.class));
        }
    }

    private void doStop(boolean doStopService) {
        Logger.d("stopping LocatorService", CLASS_NAME);
        isStarted = false;
        adapter.updateCurrentLocation("");
        unregisterReceiver(receiver);
        // If we're calling doStop() from our receiver, the service is already shutting down.
        if (doStopService) {
            stopService(new Intent(this, LocatorService.class));
        }
    }

    private boolean isServiceRunning() {
        ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (ActivityManager.RunningServiceInfo service : services) {
            if (service.service.getClassName().equals(LocatorService.class.getName())) {
                return true;
            }
        }
        return false;
    }

    private void sendBroadcast(int flag) {
        Logger.d(String.format("broadcasting flag: %d", flag), CLASS_NAME);
        Intent broadcast = new Intent();
        broadcast.putExtra("flag", flag);
        broadcast.setAction(BROADCAST_ACTION);
        sendBroadcast(broadcast);
    }
}
